//
// Created by tang on 2022/1/10.
//

#include <GLFW/glfw3.h>
#include "app/app.hpp"
#include "extension/script_base.hpp"
#include "imgui/imgui_impl_glfw.h"
#include "imgui/IconsFontAwesome4.h"
#include "imgui/stb_image.h"
#include "imgui/imgui_freetype.h"
#include "utils/path_utils.hpp"

#include "form.hpp"
#include "gui/texture.hpp"

MainFromBase::MainFromBase(std::string title, int width, int height) : m_title_(move(title)), m_init_width_(width),
m_init_height_(height)
{
}

MainFromBase::~MainFromBase() = default;

void MainFromBase::OnDraw()
{
}

void MainFromBase::SetupFonts(float fontSize)
{
    auto& io = ImGui::GetIO();
    io.Fonts->Clear();

    constexpr int order[] = { 2, 3, 1, 4 };
    bool first = true;

    for (auto i : order)
    {
        switch (i)
        {
        case 1:
        {
            // wqy-zenhei
            std::string path = "assets/wqy-microhei.ttc"_AP;
            ImFontConfig wqy_config;
            strcpy(wqy_config.Name, "WQY 米黑");
            wqy_config.MergeMode = !first;
            wqy_config.PixelSnapH = true;
            wqy_config.FontLoaderFlags = (ImGuiFreeTypeLoaderFlags_Bitmap | ImGuiFreeTypeLoaderFlags_LoadColor);
            auto font = io.Fonts->AddFontFromFileTTF(path.data(), 0.f, &wqy_config);
            if (!font)
                abort();
        }
        break;
        case 2:
        {
            // fontawesome
            std::string path = "assets/fontawesome-webfont.ttf"_AP;
            static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0, 0 };
            ImFontConfig icons_config;
            strcpy(icons_config.Name, "Font Awesome 5");
            icons_config.MergeMode = !first;
            icons_config.PixelSnapH = true;
            icons_config.FontLoaderFlags = (ImGuiFreeTypeLoaderFlags_Bitmap | ImGuiFreeTypeLoaderFlags_LoadColor);
            auto font = io.Fonts->AddFontFromFileTTF(path.data(), 0.f, &icons_config, icons_ranges);
            if (!font)
                abort();
        }
        break;
        case 3:
        {
            // source code pro
            std::string path = "assets/SourceCodePro.ttf"_AP;
            ImFontConfig icons_config;
            strcpy(icons_config.Name, "Source Code Pro Regular");
            icons_config.MergeMode = !first;
            icons_config.PixelSnapH = true;
            icons_config.FontLoaderFlags = (ImGuiFreeTypeLoaderFlags_Bitmap | ImGuiFreeTypeLoaderFlags_LoadColor);
            auto font = io.Fonts->AddFontFromFileTTF(path.data(), 0.f, &icons_config, io.Fonts->GetGlyphRangesDefault());
            if (!font)
                abort();
        }
        break;
        // case 4:
        // {
        //     // source code pro
        //     std::string path = "assets/NotoColorEmoji.ttf"_AP;
        //     // std::string path = R"(C:\Windows\Fonts\seguiemj.ttf)";
        //     ImWchar ranges[] = { 1,0x1FFFF,0 };
        //     ImFontConfig icons_config;
        //     strcpy(icons_config.Name, "Noto Color Emoji");
        //     icons_config.MergeMode = !first;
        //     icons_config.PixelSnapH = true;
        //     icons_config.FontBuilderFlags = (ImGuiFreeTypeBuilderFlags_Bitmap | ImGuiFreeTypeBuilderFlags_LoadColor);
        //     auto font = io.Fonts->AddFontFromFileTTF(path.data(),
        //         fontSize, &icons_config, ranges);
        //     if (!font)
        //         abort();
        // }
        // break;
        default:
            break;
        }
        first = false;
    }
    ImGui::GetStyle().FontSizeBase = fontSize;
}

void MainFromBase::SetupStyles()
{
    ImGui::StyleColorsDark();
    ImGuiStyle& style = ImGui::GetStyle();
    auto& io = ImGui::GetIO();
    if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        style.WindowRounding = 0.0f;
        style.Colors[ImGuiCol_WindowBg].w = 1.0f;
    }
}

static GLFWwindow* m_wnd_ = nullptr;

void MainFromBase::ToggleWindowTopmost(bool enable)
{
    glfwSetWindowAttrib(m_wnd_, GLFW_FLOATING, int(enable));
}

GLFWwindow* MainFromBase::CreateWindow(const char** glsl_version, bool maximized)
{
    assert(m_wnd_ == nullptr && "window already created!");
    // create and init window
    *glsl_version = "#version 130";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    if (maximized)
        glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);

    GLFWwindow* win = glfwCreateWindow(m_init_width_, m_init_height_, m_title_.data(), nullptr, nullptr);
    IM_ASSERT(win != nullptr && "GLFW Window create failed!!");
    glfwSetWindowSizeLimits(win, m_init_width_, m_init_height_, GLFW_DONT_CARE, GLFW_DONT_CARE);
    glfwMakeContextCurrent(win);
    glfwSwapInterval(1); // Enable V-Sync

    // config window icon
    const auto icon_path = "assets/window_icon.png"_AP;
    int w, h, c;
    stbi_uc* data = stbi_load(icon_path.data(), &w, &h, &c, 0);
    GLFWimage icon[1];
    icon->height = h;
    icon->width = w;
    icon[0].pixels = data;
    glfwSetWindowIcon(win, 1, icon);
    stbi_image_free(data);

    return m_wnd_ = win;
}

void MainFromBase::DestroyWindow(GLFWwindow* win)
{
    assert(win == m_wnd_ && "???");
    glfwDestroyWindow(win);
    m_wnd_ = nullptr;
}

void MainFromBase::ShowDialog(const std::string& dlg_name)
{
}

void MainFromBase::ShowDialog(unsigned int dlg_id)
{
}

void MainFromBase::Init()
{
    TextureManager::LoadAllTexture();
}

void MainFromBase::Cleanup()
{
    TextureManager::FreeAllTexture();
}
